// 全局变量
let statsChart;
let svg, simulation, graphData = { nodes: [], edges: [] };
let currentTheme = 'light';

// DOM元素
const domElements = {
    queryForm: document.getElementById('queryForm'),
    queryInput: document.getElementById('queryInput'),
    queryBtn: document.getElementById('queryBtn'),
    answerContent: document.getElementById('answerContent'),
    contextContainer: document.getElementById('contextContainer'),
    analysisResult: document.getElementById('analysisResult'),
    loadingIndicator: document.getElementById('loadingIndicator'),
    historyList: document.getElementById('historyList'),
    graphContainer: document.getElementById('graphContainer'),
    zoomIn: document.getElementById('zoomIn'),
    zoomOut: document.getElementById('zoomOut'),
    resetGraph: document.getElementById('resetGraph'),
    nodeCount: document.getElementById('nodeCount'),
    edgeCount: document.getElementById('edgeCount'),
    resourceSearchInput: document.getElementById('resourceSearchInput'),
    resourceSearchBtn: document.getElementById('resourceSearchBtn'),
    searchResults: document.getElementById('searchResults'),
    toggleTheme: document.getElementById('toggleTheme'),
    showHelp: document.getElementById('showHelp'),
    helpModal: document.getElementById('helpModal'),
    closeHelp: document.getElementById('closeHelp'),
    // 弹窗相关元素
    historyModal: document.getElementById('historyModal'),
    closeModal: document.getElementById('closeModal'),
    modalQuestion: document.getElementById('modalQuestion'),
    modalAnswer: document.getElementById('modalAnswer')
};

// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
    // 检查所有必需的DOM元素是否存在
    const requiredElements = ['queryForm', 'queryInput', 'queryBtn', 'answerContent', 'contextContainer', 
                             'analysisResult', 'loadingIndicator', 'historyList',
                             'graphContainer', 'resourceSearchInput', 'resourceSearchBtn', 
                             'searchResults', 'toggleTheme', 'showHelp', 'helpModal'];
    
    let missingElements = [];
    for (const elementName of requiredElements) {
        if (!domElements[elementName]) {
            missingElements.push(elementName);
        }
    }
    
    if (missingElements.length > 0) {
        console.error('Missing DOM elements:', missingElements);
        return;
    }
    
    initStatsChart();
    loadKnowledgeGraphData();
    
    // 绑定事件监听器
    bindEventListeners();
    
    // 检查本地存储的主题设置
    if (localStorage.getItem('theme') === 'dark') {
        document.body.classList.add('dark');
        domElements.toggleTheme.innerHTML = '<i class="fa fa-sun-o text-yellow-400"></i>';
    }
    
    // 初始化折叠面板功能
    initCollapsePanel();
});

// 绑定事件监听器
function bindEventListeners() {
    // 确保DOM元素存在再绑定事件
    if (!domElements.queryForm || !domElements.queryBtn || !domElements.resourceSearchBtn || !domElements.toggleTheme ||
        !domElements.showHelp || !domElements.closeHelp || !domElements.helpModal ||
        !domElements.closeModal || !domElements.historyModal) {
        console.error('Some DOM elements are missing, skipping event listener binding');
        return;
    }
    
    // 查询表单提交
    domElements.queryForm.addEventListener('submit', handleQuerySubmit);
    
    // 资源搜索
    domElements.resourceSearchBtn.addEventListener('click', handleResourceSearch);
    domElements.resourceSearchInput.addEventListener('keypress', function(event) {
        if (event.key === 'Enter') {
            handleResourceSearch();
        }
    });
    
    // 主题切换
    domElements.toggleTheme.addEventListener('click', toggleDarkMode);
    
    // 帮助模态框
    domElements.showHelp.addEventListener('click', () => {
        domElements.helpModal.classList.remove('hidden');
    });
    domElements.closeHelp.addEventListener('click', () => {
        domElements.helpModal.classList.add('hidden');
    });
    domElements.helpModal.addEventListener('click', function(event) {
        if (event.target === this) {
            this.classList.add('hidden');
        }
    });
    
    // 弹窗关闭事件
    domElements.closeModal.addEventListener('click', () => {
        domElements.historyModal.classList.add('hidden');
    });
    domElements.historyModal.addEventListener('click', function(event) {
        if (event.target === this) {
            this.classList.add('hidden');
        }
    });
}

// 初始化统计图表
function initStatsChart() {
    const ctx = document.getElementById('statsChart').getContext('2d');
    statsChart = new Chart(ctx, {
        type: 'doughnut',
        data: {
            labels: ['资源节点', '关系', '资源类别'],
            datasets: [{
                data: [0, 0, 0],
                backgroundColor: [
                    '#4F46E5',
                    '#8B5CF6',
                    '#6366F1'
                ],
                borderWidth: 0
            }]
        },
        options: {
            responsive: true,
            plugins: {
                legend: {
                    position: 'bottom',
                    labels: {
                        font: {
                            size: 11
                        }
                    }
                }
            },
            cutout: '70%'
        }
    });
}

// 处理查询提交
async function handleQuerySubmit(event) {
    event.preventDefault();
    
    const query = domElements.queryInput.value.trim();
    if (!query) return;

    // 添加表单动画效果
    const queryForm = document.getElementById('queryForm');
    queryForm.style.transform = 'translateZ(10px)';
    
    // 显示加载状态
    domElements.answerContent.innerHTML = '<div class="loading"><div class="spinner"></div><span class="ml-3">正在分析问题...</span></div>';
    domElements.answerContent.classList.add('opacity-50');
    
    domElements.queryBtn.disabled = true;
    domElements.queryBtn.textContent = '分析中...';
    domElements.queryBtn.classList.add('opacity-75');

    try {
        const response = await fetch('/api/query', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
            },
            body: JSON.stringify({ query: query })
        });

        const data = await response.json();

        if (data.success && data.data) {
            // 显示回答，添加淡入效果
            let answerToShow = data.data.answer || '暂无回答';
            // 如果没有明确的回答但有上下文，提供更友好的提示
            if ((!data.data.answer || data.data.answer.trim() === '') && data.data.context && data.data.context.length > 0) {
                answerToShow = "已找到相关上下文信息，但未能生成明确回答。请查看下方上下文信息。";
            }
            domElements.answerContent.innerHTML = marked.parse(answerToShow);

            // 添加内容显示动画
            domElements.answerContent.classList.remove('opacity-50');
            domElements.answerContent.classList.add('animate-fade-in');

            // 显示上下文信息
            if (data.data.context && data.data.context.length > 0) {
                // 获取已存在的contextList元素或创建新的
                let contextList = document.getElementById('contextList');
                if (!contextList) {
                    domElements.contextContainer.innerHTML = '<div id="contextList" class="space-y-3 p-4 hidden"></div>';
                    contextList = document.getElementById('contextList');
                } else {
                    // 清空现有内容
                    contextList.innerHTML = '';
                }

                // 填充上下文内容
                data.data.context.forEach((item, index) => {
                    const contextItem = document.createElement('div');
                    contextItem.className = 'p-4 bg-gradient-to-br from-gray-50 to-white rounded-xl border border-gray-200 text-sm shadow-sm hover:shadow-md transition-all duration-300';
                    contextItem.innerHTML = `
                        <div class="font-semibold text-gray-900 mb-2">[${index + 1}] 相关知识</div>
                        <div class="text-gray-700 whitespace-pre-wrap">${item}</div>
                    `;
                    contextList.appendChild(contextItem);
                });

                // 显示容器但默认折叠内容
                domElements.contextContainer.classList.remove('hidden');
                domElements.contextContainer.classList.add('animate-fade-in');
                contextList.classList.add('hidden');
                
                // 更新折叠面板图标状态（默认为折叠状态，不旋转）
                const contextChevron = document.getElementById('contextChevron');
                if (contextChevron) {
                    contextChevron.classList.remove('rotate-180');
                }
            } else {
                domElements.contextContainer.classList.add('hidden');
            }
            
            // 显示查询分析结果
            if (data.data.query_analysis) {
                let analysisHTML = '';
                if (data.data.query_analysis.entities && data.data.query_analysis.entities.length > 0) {
                    analysisHTML += `<div class="mb-2"><strong>实体:</strong> ${data.data.query_analysis.entities.join(', ')}</div>`;
                }
                if (data.data.query_analysis.relationships && data.data.query_analysis.relationships.length > 0) {
                    analysisHTML += `<div class="mb-2"><strong>关系:</strong> ${data.data.query_analysis.relationships.join(', ')}</div>`;
                }
                if (data.data.query_analysis.conditions && data.data.query_analysis.conditions.length > 0) {
                    analysisHTML += `<div class="mb-2"><strong>条件:</strong> ${data.data.query_analysis.conditions.join(', ')}</div>`;
                }
                if (data.data.query_analysis.query_type) {
                    analysisHTML += `<div><strong>查询类型:</strong> ${data.data.query_analysis.query_type}</div>`;
                }
                domElements.analysisResult.innerHTML = analysisHTML || '无法分析查询类型';
            }
            
            // 添加到历史记录
            addToHistory(query, data.data.answer);
            
            // 清空输入框
            domElements.queryInput.value = '';
        } else {
            domElements.answerContent.innerHTML = `<div class="text-red-500 bg-red-50 p-4 rounded-lg">查询失败: ${data.error || '未知错误'}</div>`;
            domElements.answerContent.classList.remove('opacity-50');
        }
    } catch (error) {
        console.error('查询出错:', error);
        domElements.answerContent.innerHTML = '<div class="text-red-500 bg-red-50 p-4 rounded-lg">查询过程中发生错误，请稍后重试。</div>';
        domElements.answerContent.classList.remove('opacity-50');
    } finally {
        // 恢复按钮状态和表单动画
        setTimeout(() => {
            queryForm.style.transform = 'translateZ(0)';
        }, 300);
        
        domElements.queryBtn.disabled = false;
        domElements.queryBtn.textContent = '查询';
        domElements.queryBtn.classList.remove('opacity-75');
    }
}

// 添加到历史记录
function addToHistory(query, answer) {
    // 限制历史记录数量
    const maxHistory = 10;
    
    // 检查是否已经存在相同的查询
    const existingItems = domElements.historyList.querySelectorAll('.history-item');
    for (let item of existingItems) {
        if (item.dataset.query === query) {
            return;
        }
    }
    
    // 创建历史记录项
    const historyItem = document.createElement('div');
    historyItem.className = 'history-item p-2 border border-gray-200 rounded-lg hover:bg-gray-50 cursor-pointer transition-all-300';
    historyItem.dataset.query = query;
    historyItem.innerHTML = `
        <div class="font-medium text-sm text-primary mb-1">${query}</div>
        <div class="text-gray-600 text-xs line-clamp-1">${answer || '暂无回答'}</div>
    `;
    
    // 添加点击事件，显示弹窗
    historyItem.addEventListener('click', function() {
        showModal(this.dataset.query, this.querySelector('.text-gray-600').textContent);
    });
    
    // 添加删除按钮
    const deleteBtn = document.createElement('button');
    deleteBtn.className = 'absolute top-2 right-2 text-gray-400 hover:text-red-500 p-1';
    deleteBtn.innerHTML = '<i class="fa fa-times"></i>';
    deleteBtn.addEventListener('click', function(e) {
        e.stopPropagation();
        historyItem.remove();
        
        // 如果没有历史记录了，显示提示信息
        if (domElements.historyList.children.length === 0) {
            domElements.historyList.innerHTML = '<p class="text-gray-500 italic text-center">暂无查询历史</p>';
        }
    });
    historyItem.style.position = 'relative';
    historyItem.appendChild(deleteBtn);
    
    // 清空默认提示
    if (domElements.historyList.querySelector('p.text-gray-500')) {
        domElements.historyList.innerHTML = '';
    }
    
    // 添加到历史记录列表的开头
    if (domElements.historyList.firstChild) {
        domElements.historyList.insertBefore(historyItem, domElements.historyList.firstChild);
    } else {
        domElements.historyList.appendChild(historyItem);
    }
    
    // 如果超过最大数量，删除最旧的记录
    if (domElements.historyList.children.length > maxHistory) {
        domElements.historyList.removeChild(domElements.historyList.lastChild);
    }
}

// 显示弹窗
function showModal(question, answer) {
    domElements.modalQuestion.textContent = question;
    domElements.modalAnswer.innerHTML = marked.parse(answer || '暂无回答');
    domElements.historyModal.classList.remove('hidden');
}

// 处理资源搜索
function handleResourceSearch() {
    const keyword = domElements.resourceSearchInput.value.trim();
    if (!keyword) {
        alert('请输入搜索关键词');
        return;
    }
    
    searchResources(keyword);
}

// 搜索资源
function searchResources(keyword) {
    fetch(`/api/search?keyword=${encodeURIComponent(keyword)}`)
        .then(response => response.json())
        .then(data => {
            if (data.success) {
                if (data.results && data.results.length > 0) {
                    domElements.searchResults.innerHTML = '';
                    data.results.forEach(result => {
                        const resultItem = document.createElement('div');
                        resultItem.className = 'p-3 border border-gray-200 rounded-lg hover:bg-gray-50 cursor-pointer transition-all-300';
                        resultItem.innerHTML = `
                            <div class="font-medium text-primary mb-1">${result.name}</div>
                            <div class="text-gray-600 text-xs">${result.description || '无描述信息'}</div>
                        `;
                        
                        // 添加点击事件
                        resultItem.addEventListener('click', function() {
                            // 在知识图谱中高亮显示该节点
                            highlightNode(result.id);
                            
                            // 显示与该节点相关的资源
                            fetchRelatedResources(result.id);
                        });
                        
                        domElements.searchResults.appendChild(resultItem);
                    });
                } else {
                    domElements.searchResults.innerHTML = '<p class="text-gray-500 italic text-center">未找到相关资源</p>';
                }
            } else {
                domElements.searchResults.innerHTML = `<p class="text-red-500 italic text-center">搜索失败: ${data.error}</p>`;
            }
        })
        .catch(error => {
            domElements.searchResults.innerHTML = '<p class="text-red-500 italic text-center">搜索时发生错误</p>';
        });
}

// 高亮显示节点
function highlightNode(nodeId) {
    if (!svg) return;
    
    // 重置所有节点样式
    svg.selectAll('circle').attr('r', 20).style('opacity', 1);
    
    // 高亮目标节点
    svg.selectAll('circle')
        .filter(d => d.id === nodeId)
        .attr('r', 25)
        .style('opacity', 1);
    
    // 缩放并居中到目标节点
    const node = graphData.nodes.find(n => n.id === nodeId);
    if (node) {
        // 这里可以添加缩放和居中的逻辑
    }
}

// 获取相关资源
function fetchRelatedResources(resourceId) {
    fetch(`/api/related-resources?id=${encodeURIComponent(resourceId)}&depth=2`)
        .then(response => response.json())
        .then(data => {
            if (data.success && data.related_resources && data.related_resources.length > 0) {
                // 这里可以在界面上显示相关资源
                console.log('相关资源:', data.related_resources);
            }
        })
        .catch(error => {
            console.error('获取相关资源时发生错误:', error);
        });
}

// 切换暗黑模式
function toggleDarkMode() {
    document.body.classList.toggle('dark');
    const isDarkMode = document.body.classList.contains('dark');
    
    // 更新图标
    if (isDarkMode) {
        domElements.toggleTheme.innerHTML = '<i class="fa fa-sun-o text-yellow-400"></i>';
        localStorage.setItem('theme', 'dark');
    } else {
        domElements.toggleTheme.innerHTML = '<i class="fa fa-moon-o text-gray-600"></i>';
        localStorage.setItem('theme', 'light');
    }
}

// 哈希函数，用于生成颜色
function hashCode(str) {
    let hash = 0;
    if (str.length === 0) return hash;
    for (let i = 0; i < str.length; i++) {
        const char = str.charCodeAt(i);
        hash = ((hash << 5) - hash) + char;
        hash = hash & hash; // 转换为32位整数
    }
    return hash;
}

// 根据类别获取颜色
function getColorForCategory(categoryId) {
    const colors = ['#4F46E5', '#8B5CF6', '#EC4899', '#F97316', '#10B981'];
    const colorIndex = Math.abs(hashCode(categoryId || 'default')) % colors.length;
    return colors[colorIndex];
}

// 简单的Markdown解析器
const marked = {
    parse: function(text) {
        // 简单的Markdown解析，实际项目中可以使用完整的marked库
        if (!text) return '';
        
        // 替换换行符为<br>
        let html = text.replace(/\n/g, '<br>');
        
        // 简单的粗体和斜体支持
        html = html.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
        html = html.replace(/\*(.*?)\*/g, '<em>$1</em>');
        
        // 简单的代码块支持
        html = html.replace(/`(.*?)`/g, '<code>$1</code>');
        
        return html;
    }
};

// 加载知识图谱数据
function loadKnowledgeGraphData() {
    // 检查graphContainer元素是否存在
    if (!domElements.graphContainer) {
        console.error('graphContainer element not found');
        return;
    }
    
    fetch('/api/knowledge-graph')
        .then(response => {
            // 检查响应状态
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return response.json();
        })
        .then(data => {
            if (data.success) {
                graphData = data.data;
                initKnowledgeGraph();
            } else {
                console.error('加载知识图谱数据失败:', data.error);
                domElements.graphContainer.innerHTML = `
                    <div class="flex items-center justify-center h-full">
                        <p class="text-red-500 italic">加载知识图谱失败: ${data.error || '未知错误'}</p>
                    </div>
                `;
            }
        })
        .catch(error => {
            console.error('加载知识图谱数据时发生错误:', error);
            // 确保graphContainer存在再设置innerHTML
            if (domElements.graphContainer) {
                domElements.graphContainer.innerHTML = `
                    <div class="flex items-center justify-center h-full">
                        <p class="text-red-500 italic">加载知识图谱时发生错误: ${error.message}</p>
                    </div>
                `;
            }
        });
}

// 初始化知识图谱
function initKnowledgeGraph() {
    // 检查graphContainer元素是否存在
    if (!domElements.graphContainer) {
        console.error('graphContainer element not found');
        return;
    }
    
    // 清空容器
    domElements.graphContainer.innerHTML = '';
    
    // 创建SVG
    svg = d3.select(domElements.graphContainer)
        .append('svg')
        .attr('width', '100%')
        .attr('height', '100%');
    
    const g = svg.append('g');
    
    // 创建缩放行为
    const zoom = d3.zoom()
        .scaleExtent([0.1, 4])
        .on('zoom', (event) => {
            g.attr('transform', event.transform);
        });
    
    svg.call(zoom);
    
    // 创建拖拽行为
    const drag = d3.drag()
        .on('start', dragstarted)
        .on('drag', dragged)
        .on('end', dragended);
    
    // 更新节点和边计数
    if (domElements.nodeCount) {
        domElements.nodeCount.textContent = `节点: ${graphData.nodes.length}`;
    }
    if (domElements.edgeCount) {
        domElements.edgeCount.textContent = `关系: ${graphData.edges.length}`;
    }
    
    // 更新统计图表
    if (statsChart) {
        statsChart.data.datasets[0].data = [
            graphData.nodes.length,
            graphData.edges.length,
            new Set(graphData.nodes.map(n => n.category_id)).size
        ];
        statsChart.update();
    }
    
    // 创建力导向图
    // 转换边数据以匹配D3.js力导向图的要求
    const links = graphData.edges.map(edge => ({
        source: edge.start_node_id,
        target: edge.end_node_id,
        ...edge
    }));
    
    simulation = d3.forceSimulation(graphData.nodes)
        .force('link', d3.forceLink(links).id(d => d.id).distance(100))
        .force('charge', d3.forceManyBody().strength(-300))
        .force('center', d3.forceCenter(domElements.graphContainer.clientWidth / 2, domElements.graphContainer.clientHeight / 2))
        .force('collision', d3.forceCollide().radius(40));
    
    // 创建边
    const link = g.append('g')
        .attr('stroke', '#999')
        .attr('stroke-opacity', 0.6)
        .selectAll('line')
        .data(links)
        .join('line')
        .attr('stroke-width', 2);
    
    // 创建边标签
    const linkLabel = g.append('g')
        .attr('class', 'link-labels')
        .selectAll('text')
        .data(links)
        .enter()
        .append('text')
        .text(d => d.relationship_name)
        .attr('font-size', 12)
        .attr('fill', '#666');
    
    // 创建节点
    const node = g.append('g')
        .attr('stroke', '#fff')
        .attr('stroke-width', 2)
        .selectAll('circle')
        .data(graphData.nodes)
        .join('circle')
        .attr('r', 20)
        .attr('fill', d => getColorForCategory(d.category_id))
        .call(drag);
    
    // 添加节点标签
    const nodeLabel = g.append('g')
        .attr('class', 'node-labels')
        .selectAll('text')
        .data(graphData.nodes)
        .enter()
        .append('text')
        .text(d => {
            // 截断长文本
            if (d.name && d.name.length > 8) {
                return d.name.substring(0, 8) + '...';
            }
            return d.name || '未知节点';
        })
        .attr('font-size', 12)
        .attr('text-anchor', 'middle')
        .attr('dy', 4)
        .attr('fill', 'white');
    
    // 添加节点悬停效果和详细信息显示
    node.on('mouseover', function(event, d) {
        d3.select(this).attr('r', 25).style('cursor', 'pointer');
        
        // 创建工具提示
        const tooltip = d3.select(domElements.graphContainer)
            .append('div')
            .attr('class', 'tooltip')
            .style('position', 'absolute')
            .style('background', 'rgba(0, 0, 0, 0.8)')
            .style('color', 'white')
            .style('padding', '8px')
            .style('border-radius', '4px')
            .style('font-size', '12px')
            .style('pointer-events', 'none')
            .style('z-index', '1000')
            .style('left', (event.pageX + 10) + 'px')
            .style('top', (event.pageY - 28) + 'px');
        
        // 设置工具提示内容
        let tooltipContent = `<strong>${d.name || '未知节点'}</strong>`;
        if (d.description) tooltipContent += `<br>${d.description}`;
        if (d.category_name) tooltipContent += `<br>类别: ${d.category_name}`;
        tooltip.html(tooltipContent);
    });
    
    node.on('mouseout', function(event, d) {
        d3.select(this).attr('r', 20);
        // 移除工具提示
        d3.select(domElements.graphContainer).selectAll('.tooltip').remove();
    });
    
    // 添加节点移动事件以更新工具提示位置
    node.on('mousemove', function(event, d) {
        d3.select(domElements.graphContainer).select('.tooltip')
            .style('left', (event.pageX + 10) + 'px')
            .style('top', (event.pageY - 28) + 'px');
    });
    
    // 节点点击事件
    node.on('click', function(event, d) {
        // 显示与该节点相关的资源
        fetchRelatedResources(d.id);
    });
    
    // 添加边悬停效果和详细信息显示
    link.on('mouseover', function(event, d) {
        d3.select(this).attr('stroke-width', 4).attr('stroke', '#4F46E5');
        
        // 创建工具提示
        const tooltip = d3.select(domElements.graphContainer)
            .append('div')
            .attr('class', 'tooltip')
            .style('position', 'absolute')
            .style('background', 'rgba(0, 0, 0, 0.8)')
            .style('color', 'white')
            .style('padding', '8px')
            .style('border-radius', '4px')
            .style('font-size', '12px')
            .style('pointer-events', 'none')
            .style('z-index', '1000')
            .style('left', (event.pageX + 10) + 'px')
            .style('top', (event.pageY - 28) + 'px');
        
        // 设置工具提示内容
        let tooltipContent = `<strong>${d.relationship_name || '未知关系'}</strong>`;
        if (d.description) tooltipContent += `<br>${d.description}`;
        tooltip.html(tooltipContent);
    });
    
    link.on('mouseout', function(event, d) {
        d3.select(this).attr('stroke-width', 2).attr('stroke', '#999');
        // 移除工具提示
        d3.select(domElements.graphContainer).selectAll('.tooltip').remove();
    });
    
    // 添加边移动事件以更新工具提示位置
    link.on('mousemove', function(event, d) {
        d3.select(domElements.graphContainer).select('.tooltip')
            .style('left', (event.pageX + 10) + 'px')
            .style('top', (event.pageY - 28) + 'px');
    });
    
    // 更新力导向图
    simulation.on('tick', () => {
        link
            .attr('x1', d => d.source.x)
            .attr('y1', d => d.source.y)
            .attr('x2', d => d.target.x)
            .attr('y2', d => d.target.y);
        
        node
            .attr('cx', d => d.x)
            .attr('cy', d => d.y);
        
        nodeLabel
            .attr('x', d => d.x)
            .attr('y', d => d.y);
        
        // 更新边标签位置
        linkLabel
            .attr('x', d => (d.source.x + d.target.x) / 2)
            .attr('y', d => (d.source.y + d.target.y) / 2);
    });
    
    // 缩放控制
    if (domElements.zoomIn) {
        domElements.zoomIn.addEventListener('click', () => {
            svg.transition().call(zoom.scaleBy, 1.2);
        });
    }
    
    if (domElements.zoomOut) {
        domElements.zoomOut.addEventListener('click', () => {
            svg.transition().call(zoom.scaleBy, 0.8);
        });
    }
    
    if (domElements.resetGraph) {
        domElements.resetGraph.addEventListener('click', () => {
            svg.transition().call(zoom.transform, d3.zoomIdentity);
            simulation.alpha(1).restart();
        });
    }
    
    // 拖拽相关函数
    function dragstarted(event, d) {
        if (!event.active) simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
    }
    
    function dragged(event, d) {
        d.fx = event.x;
        d.fy = event.y;
    }
    
    function dragended(event, d) {
        if (!event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
    }
}

// 根据类别获取颜色
function getColorForCategory(category) {
    const colorMap = {
        '服务器': '#ff7f0e',
        '数据库': '#2ca02c',
        '网络设备': '#d62728',
        '存储设备': '#9467bd',
        '应用': '#8c564b',
        '虚拟机': '#e377c2',
        '物理机': '#7f7f7f',
        '容器': '#bcbd22',
        '默认': '#1f77b4'
    };
    
    return colorMap[category] || colorMap['默认'];
}

// 初始化折叠面板功能
function initCollapsePanel() {
    const contextHeader = document.getElementById('contextHeader');
    const contextList = document.getElementById('contextList');
    const contextChevron = document.getElementById('contextChevron');

    if (contextHeader && contextList && contextChevron) {
        // 设置初始状态为折叠
        contextList.classList.add('hidden');
        
        contextHeader.addEventListener('click', function() {
            // 切换折叠状态
            contextList.classList.toggle('hidden');
            
            // 添加旋转动画
            contextChevron.classList.toggle('rotate-180');
            
            // 添加缩放动画效果
            if (!contextList.classList.contains('hidden')) {
                contextList.style.opacity = '0';
                contextList.style.transform = 'scaleY(0.8)';
                contextList.style.transition = 'all 0.3s ease';
                
                // 触发重排
                contextList.offsetHeight;
                
                // 展开动画
                contextList.style.opacity = '1';
                contextList.style.transform = 'scaleY(1)';
            }
        });
    }
}